<template>
  <a-select v-model="modelValue"
            v-bind="options"
            :disabled="disabled"
            class="ly-margin-right-bottom-sm"
            @visible-change="onVisibleChange"
            @change="onChange"
            :multiple="multiple"
            filterable
            @clear="clear">
    <a-select-option v-for="v in optionList"
                     :key="v.value"
                     :label="v.label"
                     :title="v.label"
                     :value="v.value"
                     :disabled="Boolean(v.disabled)"
                     :clearable="Boolean(v.clearable)"/>
  </a-select>
</template>

<script lang="ts">
  import { Component, Vue, Prop, Model, Watch, Emit } from 'vue-property-decorator'
  import { ValueType, LazySelectElm } from './definitions/LazySelectType'

  @Component
  export default class LazySelectMain extends Vue {
    @Model('model')
    protected value!: ValueType | ValueType[]

    // 所有的el-select选项
    @Prop({
      type: Object,
      default() {
        return {}
      }
    })
    protected options!: LazySelectElm

    // 返回Promise/数据数组
    // 数据必须是包含{value: '', label: ''}结构的对象数组
    @Prop({
      type: [Function, Array]
    })
    protected getDataFnOrDataList!: (() => Promise<LazySelectElm[]>) | LazySelectElm[]

    // 是否缓存数据
    @Prop({
      type: Boolean,
      default: true
    })
    protected cache!: boolean

    // 是否禁用
    @Prop({
      type: Boolean,
      default: false
    })
    protected disabled!: boolean

    // 是否多选
    @Prop({
      type: Boolean,
      default: false
    })
    protected multiple!: boolean

    protected initial: boolean = false
    protected optionList: LazySelectElm[] = []

    protected get modelValue() {
      return this.value
    }

    protected set modelValue(val: ValueType | ValueType[]) {
      this.emitModel(val)
    }

    protected get optionMap() {
      const optionMap: any = {}
      this.optionList.forEach((v: any) => {
        optionMap[v.value] = v
      })
      return optionMap
    }

    public getObj(value: ValueType | ValueType[]) {
      return Array.isArray(value) ? value.map(v => this.optionMap[v]) : this.optionMap[value]
    }

    public getDataList() {
      if (typeof this.getDataFnOrDataList === 'function') {
        this.getDataFnOrDataList().then(
          data => {
            this.setDataList(data)
          },
          () => {
            // 异常情况下，下次重新请求
            this.initial = false
          }
        )
      }
    }

    public setDataList(dataList: LazySelectElm[]) {
      this.optionList = dataList
      this.initial = true
      this.emitInitial(this.optionList)
    }

    @Watch('value')
    protected watchValue() {
      this.autoGetData()
    }

    @Watch('getDataFnOrDataList')
    protected watchGetDataFnOrDataList(val: (() => Promise<LazySelectElm[]>) | LazySelectElm[]) {
      if (Array.isArray(val)) {
        this.autoGetData()
      }
    }

    protected created() {
      this.autoGetData()
    }

    protected handleEvents() {
    }

    protected autoGetData() {
      const val = this.value
      const isArr = Array.isArray(val)
      if ((isArr && (val as ValueType[])[0]) || (!isArr && val)) {
        this.onVisibleChange(true)
      }
    }

    protected onVisibleChange(visible: boolean) {
      this.emitOnVisible(visible)
      if (visible && (this.initial === false || !this.cache)) {
        const isArr = Array.isArray(this.getDataFnOrDataList)
        const isFn = !isArr && typeof this.getDataFnOrDataList === 'function'
        if (!isArr && !isFn) {
          throw new Error('必须提供 getDataFnOrDataList([Array | Function:Promise]) ')
        }
        if (Array.isArray(this.getDataFnOrDataList)) {
          this.setDataList(this.getDataFnOrDataList)
        } else if (isFn) {
          this.getDataList()
        }
      }
    }

    protected clear() {
      // this.optionList = []
      // this.initial = false
      this.emitClear()
    }

    protected onChange(val: [number, string]) {
      this.emitChange(val)
    }

    @Emit('model')
    private emitModel(val: ValueType | ValueType[]) {
    }

    @Emit('initial')
    private emitInitial(val: LazySelectElm[]) {
    }

    @Emit('clear')
    private emitClear() {
    }

    @Emit('change')
    private emitChange(val: ValueType | ValueType[]) {
    }

    @Emit('onVisible')
    private emitOnVisible(val: boolean) {
    }
  }
</script>
